package org.termine.jsf;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

import org.primefaces.event.ScheduleEntrySelectEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.termine.entity.ClientProviderScheduleEvent;
import org.termine.logic.AppointmentManager;

@ManagedBean
@ViewScoped
public class ProviderScheduleJSF extends BaseJSF implements Serializable {

	private static final long serialVersionUID = 7032561986237645958L;
	private static final Logger logger = LoggerFactory.getLogger(ProviderScheduleJSF.class);

	@ManagedProperty(value = "#{loginJSF}")
	private LoginJSF loginJSF;
	@ManagedProperty(value = "#{appointmentManager}")
	private AppointmentManager appointmentManager;

	private ScheduleModel providerScheduleModel;
	private ClientProviderScheduleEvent event;
	private Date exportStart;
	private Date exportEnd;

	/*
	 * Init
	 */
	@PostConstruct
	public void init() {
		this.event = new ClientProviderScheduleEvent();
		providerScheduleModel = new DefaultScheduleModel();
		List<ClientProviderScheduleEvent> appointments = getAppointmentManager()
				.getAllAppointmentsForProvider(getLoginJSF().getPersonalData().getProvider_id());
		for (int i = 0; i < appointments.size(); i++) {
			providerScheduleModel.addEvent(appointments.get(i));
		}
	}

	/*
	 * Jsf Action Methods
	 */
	public String exportScheduleEntries() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		ExternalContext externalContext = facesContext.getExternalContext();
		HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

		response.reset();
		response.setContentType("application/xml");
		response.setHeader("Content-disposition", "attachment; filename=\"mySchedule.xml\"");

		BufferedInputStream input = null;
		BufferedOutputStream output = null;

		InputStream result = getAppointmentManager().getAllAppointmentsForProvider(
				getExportStart(), getExportEnd(), getLoginJSF().getPersonalData().getProvider_id());

		if (result == null) {
			setExportEnd(null);
			setExportStart(null);
			setErrorMessage("There are no appointments in the given timeframe.");
			return "NO_SCHEDULE_ENTRIES";
		} else {
			try {
				input = new BufferedInputStream(result);
				output = new BufferedOutputStream(response.getOutputStream());

				byte[] buffer = new byte[10240];
				for (int length; (length = input.read(buffer)) > 0;) {
					output.write(buffer, 0, length);
				}
			} catch (Exception e) {
				logger.error("error: {}", e);
			} finally {
				try {
					output.close();
					input.close();
				} catch (Exception e) {
					logger.error("error: {}", e);
				}
			}
			facesContext.responseComplete();
			return "SUCCESS";
		}
	}

	public String cancelAppointment() {
		if (getAppointmentManager().cancelAppointment(event, getLoginJSF().getWhoAmI())) {
			init();
			return "SUCCESS";
		}
		return "ERROR";
	}

	public void onEventSelect(ScheduleEntrySelectEvent selectEvent) {
		event = (ClientProviderScheduleEvent) selectEvent.getScheduleEvent();
	}

	/*
	 * Getters & Setters
	 */
	public Date getExportStart() {
		return exportStart;
	}

	public void setExportStart(Date exportStart) {
		this.exportStart = exportStart;
	}

	public Date getExportEnd() {
		return exportEnd;
	}

	public void setExportEnd(Date exportEnd) {
		this.exportEnd = exportEnd;
	}

	public LoginJSF getLoginJSF() {
		return loginJSF;
	}

	public void setLoginJSF(LoginJSF loginJSF) {
		this.loginJSF = loginJSF;
	}

	public AppointmentManager getAppointmentManager() {
		return appointmentManager;
	}

	public void setAppointmentManager(AppointmentManager appointmentManager) {
		this.appointmentManager = appointmentManager;
	}

	public ScheduleModel getProviderScheduleModel() {
		return providerScheduleModel;
	}

	public void setProviderScheduleModel(ScheduleModel providerScheduleModel) {
		this.providerScheduleModel = providerScheduleModel;
	}

	public ClientProviderScheduleEvent getEvent() {
		return event;
	}

	public void setEvent(ClientProviderScheduleEvent event) {
		this.event = event;
	}
}
